<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket测试工具</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            max-width: 800px;
            margin: 0 auto;
            padding: 20px;
        }
        .container {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }
        .controls {
            display: flex;
            gap: 10px;
            align-items: center;
        }
        input, button {
            padding: 8px;
            font-size: 16px;
        }
        .logs {
            border: 1px solid #ccc;
            padding: 10px;
            height: 300px;
            overflow-y: auto;
            background-color: #f5f5f5;
            white-space: pre-wrap;
        }
        .messages {
            border: 1px solid #ccc;
            padding: 10px;
            height: 300px;
            overflow-y: auto;
            background-color: #f9f9f9;
        }
        .message-item {
            border-bottom: 1px solid #eee;
            padding: 8px 0;
        }
        .status {
            padding: 10px;
            border-radius: 5px;
            margin-bottom: 10px;
        }
        .status-connected {
            background-color: #d4edda;
            color: #155724;
        }
        .status-disconnected {
            background-color: #f8d7da;
            color: #721c24;
        }
        .channel-list {
            margin-top: 10px;
        }
        .channel-item {
            display: flex;
            justify-content: space-between;
            padding: 5px;
            background-color: #e9ecef;
            margin-bottom: 5px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>WebSocket测试工具</h1>
        
        <div id="status" class="status status-disconnected">
            状态: 未连接
        </div>
        
        <div class="controls">
            <input type="text" id="ws-url" value="ws://localhost:8080/ws" placeholder="WebSocket URL">
            <button id="connect-btn">连接</button>
            <button id="disconnect-btn" disabled>断开连接</button>
        </div>
        
        <div class="controls">
            <input type="text" id="channel" placeholder="频道名称，如kline_BTCUSDT_1m">
            <button id="subscribe-btn" disabled>订阅</button>
            <button id="unsubscribe-btn" disabled>取消订阅</button>
        </div>
        
        <div class="channel-list">
            <h3>已订阅频道:</h3>
            <div id="subscribed-channels"></div>
        </div>
        
        <div>
            <h3>日志:</h3>
            <div id="logs" class="logs"></div>
        </div>
        
        <div>
            <h3>接收到的消息:</h3>
            <div id="messages" class="messages"></div>
        </div>
    </div>

    <script>
        // DOM 元素
        const wsUrlInput = document.getElementById('ws-url');
        const connectBtn = document.getElementById('connect-btn');
        const disconnectBtn = document.getElementById('disconnect-btn');
        const channelInput = document.getElementById('channel');
        const subscribeBtn = document.getElementById('subscribe-btn');
        const unsubscribeBtn = document.getElementById('unsubscribe-btn');
        const statusElement = document.getElementById('status');
        const logsElement = document.getElementById('logs');
        const messagesElement = document.getElementById('messages');
        const subscribedChannelsElement = document.getElementById('subscribed-channels');
        
        // WebSocket 对象
        let socket = null;
        let subscribedChannels = new Set();
        
        // 添加日志
        function addLog(message) {
            const timestamp = new Date().toLocaleTimeString();
            logsElement.innerHTML += `[${timestamp}] ${message}\n`;
            logsElement.scrollTop = logsElement.scrollHeight;
        }
        
        // 添加消息
        function addMessage(message) {
            const messageItem = document.createElement('div');
            messageItem.className = 'message-item';
            messageItem.textContent = message;
            messagesElement.prepend(messageItem);
        }
        
        // 更新订阅频道列表
        function updateSubscribedChannels() {
            subscribedChannelsElement.innerHTML = '';
            if (subscribedChannels.size === 0) {
                subscribedChannelsElement.innerHTML = '<p>无订阅频道</p>';
                return;
            }
            
            subscribedChannels.forEach(channel => {
                const channelItem = document.createElement('div');
                channelItem.className = 'channel-item';
                channelItem.innerHTML = `
                    <span>${channel}</span>
                    <button class="unsubscribe-single" data-channel="${channel}">取消订阅</button>
                `;
                subscribedChannelsElement.appendChild(channelItem);
            });
            
            // 添加单个取消订阅事件
            document.querySelectorAll('.unsubscribe-single').forEach(btn => {
                btn.addEventListener('click', function() {
                    const channel = this.getAttribute('data-channel');
                    unsubscribeChannel(channel);
                });
            });
        }
        
        // 连接WebSocket
        function connect() {
            const url = wsUrlInput.value;
            
            try {
                socket = new WebSocket(url);
                
                socket.onopen = function() {
                    addLog(`WebSocket连接已建立: ${url}`);
                    statusElement.className = 'status status-connected';
                    statusElement.textContent = '状态: 已连接';
                    connectBtn.disabled = true;
                    disconnectBtn.disabled = false;
                    subscribeBtn.disabled = false;
                    unsubscribeBtn.disabled = false;
                };
                
                socket.onmessage = function(event) {
                    addLog(`接收到消息: ${event.data}`);
                    
                    try {
                        // 尝试解析JSON
                        const parsed = JSON.parse(event.data);
                        addMessage(`类型: ${parsed.type || '未知'}, 频道: ${parsed.channel || '未知'}\n数据: ${JSON.stringify(parsed.data || parsed, null, 2)}`);
                    } catch (e) {
                        addLog(`消息解析错误: ${e.message}`);
                        addMessage(`原始消息: ${event.data}`);
                    }
                };
                
                socket.onclose = function(event) {
                    addLog(`WebSocket连接已关闭 (代码: ${event.code}, 原因: ${event.reason || '未知'})`);
                    statusElement.className = 'status status-disconnected';
                    statusElement.textContent = '状态: 未连接';
                    connectBtn.disabled = false;
                    disconnectBtn.disabled = true;
                    subscribeBtn.disabled = true;
                    unsubscribeBtn.disabled = true;
                    subscribedChannels.clear();
                    updateSubscribedChannels();
                };
                
                socket.onerror = function(error) {
                    addLog(`WebSocket错误: ${error.message || '未知错误'}`);
                };
            } catch (e) {
                addLog(`连接失败: ${e.message}`);
            }
        }
        
        // 断开连接
        function disconnect() {
            if (socket) {
                socket.close();
                socket = null;
            }
        }
        
        // 订阅频道
        function subscribeChannel(channel) {
            if (!socket || socket.readyState !== WebSocket.OPEN) {
                addLog('WebSocket未连接');
                return;
            }
            
            if (!channel) {
                addLog('请输入频道名称');
                return;
            }
            
            const message = JSON.stringify({
                type: 'subscribe',
                channel: channel
            });
            
            socket.send(message);
            subscribedChannels.add(channel);
            updateSubscribedChannels();
            addLog(`已发送订阅请求: ${channel}`);
        }
        
        // 取消订阅频道
        function unsubscribeChannel(channel) {
            if (!socket || socket.readyState !== WebSocket.OPEN) {
                addLog('WebSocket未连接');
                return;
            }
            
            if (!channel) {
                addLog('请输入频道名称');
                return;
            }
            
            const message = JSON.stringify({
                type: 'unsubscribe',
                channel: channel
            });
            
            socket.send(message);
            subscribedChannels.delete(channel);
            updateSubscribedChannels();
            addLog(`已发送取消订阅请求: ${channel}`);
        }
        
        // 事件监听
        connectBtn.addEventListener('click', connect);
        disconnectBtn.addEventListener('click', disconnect);
        subscribeBtn.addEventListener('click', function() {
            subscribeChannel(channelInput.value);
        });
        unsubscribeBtn.addEventListener('click', function() {
            unsubscribeChannel(channelInput.value);
        });
        
        // 添加常用频道快速订阅按钮
        const commonChannels = [
            'kline_BTCUSDT_1m',
            'kline_BTCUSDT_5m',
            'kline_BTCUSDT_15m',
            'kline_BTCUSDT_1h',
            'kline_BTCUSDT_1d',
            'trade_BTCUSDT',
            'depth_BTCUSDT'
        ];
        
        const quickSubscribeDiv = document.createElement('div');
        quickSubscribeDiv.className = 'quick-subscribe';
        quickSubscribeDiv.innerHTML = '<h3>快速订阅:</h3>';
        
        const buttonsContainer = document.createElement('div');
        buttonsContainer.style.display = 'flex';
        buttonsContainer.style.flexWrap = 'wrap';
        buttonsContainer.style.gap = '5px';
        
        commonChannels.forEach(channel => {
            const btn = document.createElement('button');
            btn.textContent = channel;
            btn.style.padding = '5px 10px';
            btn.style.fontSize = '14px';
            btn.addEventListener('click', function() {
                channelInput.value = channel;
                subscribeChannel(channel);
            });
            buttonsContainer.appendChild(btn);
        });
        
        quickSubscribeDiv.appendChild(buttonsContainer);
        document.querySelector('.container').insertBefore(quickSubscribeDiv, document.querySelector('.channel-list'));
        
        // 页面加载时自动连接
        window.addEventListener('load', function() {
            setTimeout(connect, 1000);
        });
    </script>
</body>
</html>